package org.videopractice.media;

import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.view.Surface;

import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * Media编码器
 */
public class MediaEncoder extends Thread {

    private final MediaCodec mediaCodec;
    private final MediaDataHandler mediaDataHandler;

    private volatile boolean isEncoding = true;

    public MediaEncoder(MediaDataHandler mediaDataHandler) throws IOException {
        mediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
        this.mediaDataHandler = mediaDataHandler;
    }

    public MediaEncoder preReady(int width, int height) {
        // 创建一个H264的配置格式
        MediaFormat mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);
        // 设置颜色格式
        mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        // 设置比特率(设置码率，通常码率越高，视频越清晰)
        mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 1000 * 1024);//400_000);
        // 设置帧率
        mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
        // 关键帧间隔时间，通常情况下，你设置成多少问题都不大,直播种可能要求高频I帧这样进入直播后不必等待太久才看到画面，因为没有I帧无法显示。
        mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);

        // 设置配置到 mediaCodec，参数信息: 格式配置信息（必填）, 表层用于展示选填, 加密方式（选填）, 作用标记（这里是用来解码）
        mediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
        return this;
    }

    public Surface createInputSurface() {
        return mediaCodec.createInputSurface();
    }

    public void startEncode() {
        isEncoding = true;
        if(!isAlive()) {
            start();
        }
    }

    public void stopEncode() {
        isEncoding = false;
    }

    @Override
    public void run() {
        mediaCodec.start();

        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo(); // 出参
        while (isEncoding) {
            // 取出解码数据
            int outputIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000); // 10毫秒， us是微妙的意思
            if(outputIndex >= 0) {
                // 取出解码好的buffer数据:YUV数据
                ByteBuffer outputBuffer = mediaCodec.getOutputBuffer(outputIndex);
                byte[] outputData = new byte[bufferInfo.size];
                outputBuffer.get(outputData);

                mediaDataHandler.doHandler(new MediaDataPackage(outputData, bufferInfo.presentationTimeUs / 1000));

                mediaCodec.releaseOutputBuffer(outputIndex, false);
            }
        }

        mediaCodec.reset();
        mediaCodec.stop();
        mediaCodec.release();
    }

    // 媒体数据处理器
    public interface MediaDataHandler {
        void doHandler(MediaDataPackage dataPackage);
    }

}
